﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Collections;

namespace ExpenseSystem.Common.BaseModel
{
    //EModel仅用于类型约束，没有实在意义
    public abstract class EModel 
    {
    }
    public abstract class SuperModel:EModel
    {
        [NotDataColumnAttribute]
        public virtual IList<String> PropertyUpdated { get; private set; }
        public void ResetUpdateTrace()
        {
            PropertyUpdated.Clear();
        }
        public SuperModel()
        {
            PropertyUpdated = new List<String>();
        }
        public virtual void Merge<T>(T other) where T : SuperModel, new()
        {
            if (other.GetType() != this.GetType())
            {
                throw new ArgumentException("Merge对象类型必须与属性类型保持一致");
            }
            this.PropertyUpdated.Clear();
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (property.GetCustomAttribute<NotDataColumnAttribute>() == null)
                {
                    property.SetValue(this, property.GetValue(other));
                }
            }
        }
        public virtual IList<PropertyInfo> Compare<T>(T other) where T : SuperModel
        {
            Type myType = this.GetType();
            if (typeof(T) != myType)
            {
                throw new ArgumentException(String.Format("必须传入参数{0}", myType));
            }
            if (other == null)
            {
                throw new ArgumentNullException("Compare方法传入的参数为空");
            }
            IList<PropertyInfo> result = new List<PropertyInfo>();
            PropertyInfo[] properties = myType.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (property.GetValue(this) != property.GetValue(other))
                {
                    result.Add(property);
                }
            }
            return result;
        }
        private long _autoId;
        private string _creator;
        private string _modifier;
        private string _createdate;
        private string _modifydate;
        private int _flag;
        private bool _avaliable;

        public virtual long AutoId
        {
            get { return _autoId; }
            set
            {
                if (_autoId == value)
                    return;
                if (_autoId == 0)
                {
                    _autoId = value;
                    if (!PropertyUpdated.Contains("AutoId"))
                        PropertyUpdated.Add("AutoId");
                }
                else if (_autoId != value)
                {
                    throw new MemberAccessException();
                }
            }
        }
        public virtual string CreateDate
        {
            get { return _createdate; }
            set
            {
                if (_createdate == value)
                    return;
                if (String.IsNullOrWhiteSpace(_createdate))
                {
                    _createdate = value;
                    if (!PropertyUpdated.Contains("CreateDate"))
                        PropertyUpdated.Add("CreateDate");
                }
            }
        }
        public virtual string Creator
        {
            get { return _creator; }
            set
            {
                if (_creator == value)
                    return;
                if (String.IsNullOrWhiteSpace(_creator))
                {
                    _creator = value;
                    if (!PropertyUpdated.Contains("Creator"))
                        PropertyUpdated.Add("Creator");
                }
            }
        }

        public virtual string ModifyDate
        {
            get { return _modifydate; }
            set
            {
                if (_modifydate == value)
                    return;
                _modifydate = value;
                if (!PropertyUpdated.Contains("ModifyDate"))
                    PropertyUpdated.Add("ModifyDate");

            }
        }
        public virtual string Modifier
        {
            get { return _modifier; }
            set
            {
                if (_modifier == value)
                    return;
                _modifier = value;
                if (!PropertyUpdated.Contains("Modifier"))
                    PropertyUpdated.Add("Modifier");

            }
        }

        public virtual int Flag
        {
            get { return _flag; }
            set
            {
                if (_flag == value)
                    return;
                _flag = value;
                if (!PropertyUpdated.Contains("Flag"))
                    PropertyUpdated.Add("Flag");
            }
        }
        public virtual bool Avaliable
        {
            get { return _avaliable; }
            set
            {
                if (_avaliable == value)
                    return;
                _avaliable = value;
                if (!PropertyUpdated.Contains("Avaliable"))
                    PropertyUpdated.Add("Avaliable");
            }
        }
    }
}
